Scene2D.prototype = new Shape();  
Scene2D.prototype.constructor=Scene2D;
function Scene2D(canvasId){
	/* INIT SECTION */
	var self = this;
	this.canvas = document.getElementById(canvasId);
	this.context = this.canvas.getContext("2d");
	this.scene = this;
	this.domUtils = new DomUtils();
	this.type = "2D";
	
	/* END INIT SECTION */
	
	/*  FIND SHAPES FUNCTIONS */
	this.getShapesInBoundary = function(boundary, excludedShape){
		var shapes = new Array();
		if(!excludedShape) excludedShape=null;
		for(var i=0;i<this.shapes.length;i++){		
			var shape = this.shapes[i];
			if(shape==excludedShape) continue;
			if(shape.intersectsBoundary(this,boundary)){
				shapes.push(shape);
			}			
		}
		return shapes;
	};
	this.getShapesOfPoint = function(point){
		var shapes = new Array();
		for(var k=0; k<this.shapes.length;k++){
			var shape = this.shapes[k];
			if(shape.boundary.x<=point.x && shape.boundary.x+shape.boundary.w>=point.x &&
			shape.boundary.y<=point.y && shape.boundary.y+shape.boundary.h>=point.y){
				shapes.push(shape);
			}
		}		
		return shapes;
	};
	/* END FIND SHAPES FUNCTIONS */
	
	/* VECTORIALIZATION FUNCTIONS */
	this.draw = function(shapes){
		if(!shapes) shapes = this.shapes;
		shapes = shapes.sort(function(a, b){return a.zIndex-b.zIndex});
		
		for(var k in shapes){
			var shape = shapes[k];
			shape.draw(this.context);
		}
	};
	
	this.enableClipping = true;
	this.invalidate = function(options){
		var self = this;
		var boundary = null;
		var excludedShape = null;
		if(options && options.boundary) boundary = options.boundary;
		if(options && options.shape){
			if(!boundary) boundary = options.shape.boundary;
			excludedShape = options.shape;
		}		
		if(boundary){
			if(boundary.x && boundary.y && boundary.w && boundary.h){
				if(this.enableClipping){
					this.context.save();
					this.context.rect(boundary.x,boundary.y,boundary.w,boundary.h);
					this.context.clip();
				}
				
				this.context.clearRect(boundary.x,boundary.y,boundary.w,boundary.h);
				var shapes = self.getShapesInBoundary(boundary,excludedShape);				
				self.draw(shapes);
				if(this.enableClipping){
					this.context.restore();
				}
			}
		}
		else{
			this.context.clearRect(0,0, this.canvas.width, this.canvas.height);
			this.draw();
		}
	};
	
	this.clear = function(){
		this.shapes = new Array();
		this.invalidate();
	}
	
	/* END VECTORIALIZATION FUNCTIONS */
	
	/* APPEARANCE FUNCTIONS */
	this.setBackgroundImage = function(url){
		this.canvas.style.background = "url('"+url+"')";
	};
	
	this.setBackgroundColor = function(color){
		this.canvas.style.background = color;
	};
	
	this.getSize = function(){
		return {w:this.canvas.width,h:this.canvas.height};
	}
	/* END APPEARANCE FUNCTIONS */
	
	/*  ATTACH EVENTS */
	this.attachEvents = function(){
		var self = this;
		var mouseEvent = function(event, type){	
		  self.domUtils.cancelEvent(event);
		  var x = 0;
		  var y = 0;
		  if(event.x){
			   x = event.x;
			   y = event.y;
		   }
		   else{
			x = event.clientX;
			y = event.clientY;
		   }
		  var canvasOffset = self.domUtils.getOffset(self.canvas);
		  x -= canvasOffset.left;
		  y -= canvasOffset.top;
		  var pos = {x:x,y:y};		  
		  if(type=="mousedown"){
			self.mouseDown(pos);
		  }
		  if(type=="mouseup"){
			self.mouseUp(pos);
		  }
		  if(type=="mousemove"){			
			self.mouseMove(pos);
		  }
		  var shapes = self.getShapesOfPoint({x:x,y:y});
		  shapes = shapes.sort(function(a, b){return b.zIndex-a.zIndex});
		  if(type=="mousedown"){
			for(var k in shapes){
				if(shapes[k].allowMouseDownEvent(pos)){		
					shapes[k].mouseDown(pos);				
					break;
				}
			}
		  }
		  for(var k in self.shapes){
			if(self.shapes[k].allowMouseEvents()){
				if(type=="mousemove")
					self.shapes[k].mouseMove(pos);
				
				if(type=="mouseup")
					self.shapes[k].mouseUp(pos);
			}
		  }
		}
		this.domUtils.addEventSimple(this.canvas, "mousemove", function(event){mouseEvent(event,"mousemove")});
		this.domUtils.addEventSimple(this.canvas, "mousedown", function(event){mouseEvent(event,"mousedown")});
		this.domUtils.addEventSimple(this.canvas, "mouseup", function(event){mouseEvent(event,"mouseup")});
		
		
		// this.domUtils.addEventSimple(this.canvas, "touchstart", function(event){mouseEvent(event,"mousedown")});
		// this.domUtils.addEventSimple(this.canvas, "touchmove", function(event){mouseEvent(event,"mouseup")});
		// this.domUtils.addEventSimple(this.canvas, "touchend", function(event){mouseEvent(event,"mousemove")});
		// this.canvas.addEventListener("mousedown", function(){mouseEvent(event,"mousedown")},false);
		// this.canvas.addEventListener("mouseup", function(){mouseEvent(event,"mouseup")},false);
		// this.canvas.addEventListener("mousemove", function(){mouseEvent(event,"mousemove")},false);
	}
	
	this.attachEvents();
	/*  END ATTACH EVENTS */
}

function Scene(canvasId, type){
	if(type=="2D"){
		return new Scene2D(canvasId);
	}
	if(type=="3D"){
		return new Scene3D(canvasId);
	}
	return new Scene2D(canvasId);
}